package com.castle.fortress.admin.study.exam.service.impl;

import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.castle.fortress.admin.member.service.MemberAuthorityService;
import com.castle.fortress.admin.study.exam.dto.StudyExamDto;
import com.castle.fortress.admin.study.exam.entity.StudyExamEntity;
import com.castle.fortress.admin.study.exam.entity.StudyExamStatisticsEntity;
import com.castle.fortress.admin.study.exam.entity.StudyExamStatisticsMemberEntity;
import com.castle.fortress.admin.study.exam.entity.StudyMemberUnfinishExamEntity;
import com.castle.fortress.admin.study.exam.mapper.*;
import com.castle.fortress.admin.study.exam.service.StudyExamService;
import com.castle.fortress.admin.utils.BizCommonUtil;
import com.castle.fortress.admin.utils.WebUtil;
import com.castle.fortress.common.enums.AuthorityTypeEnum;
import com.castle.fortress.common.enums.ExamStatusEnum;
import com.castle.fortress.common.enums.YesNoEnum;
import com.castle.fortress.common.utils.ConvertUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;

import java.util.*;

/**
 * 试卷管理 服务实现类
 *
 * @author castle
 * @since 2023-02-10
 */
@Service
public class StudyExamServiceImpl extends ServiceImpl<StudyExamMapper, StudyExamEntity> implements StudyExamService {
    @Autowired
    private MemberAuthorityService memberAuthorityService;
    @Autowired
    private StudyExamStatisticsMapper studyExamStatisticsMapper;
    @Autowired
    private StudyExamStatisticsMemberMapper studyExamStatisticsMemberMapper;
    @Autowired
    private StudyMemberExamMapper studyMemberExamMapper;
    @Autowired
    private StudyMemberUnfinishExamMapper studyMemberUnfinishExamMapper;
    /**
    * 获取查询条件
    * @param studyExamDto
    * @return
    */
    public QueryWrapper<StudyExamEntity> getWrapper(StudyExamDto studyExamDto){
        QueryWrapper<StudyExamEntity> wrapper= new QueryWrapper();
        if(studyExamDto != null){
            StudyExamEntity studyExamEntity = ConvertUtil.transformObj(studyExamDto,StudyExamEntity.class);
            wrapper.like(StrUtil.isNotEmpty(studyExamEntity.getExamName()),"exam_name",studyExamEntity.getExamName());
            wrapper.like(studyExamEntity.getExamStartTime() != null,"exam_start_time",studyExamEntity.getExamStartTime());
            wrapper.eq(studyExamEntity.getStatus() != null,"status",studyExamEntity.getStatus());
            wrapper.orderByDesc("create_time");
        }
        return wrapper;
    }


    @Override
    public IPage<StudyExamDto> pageStudyExam(Page<StudyExamDto> page, StudyExamDto studyExamDto) {
        QueryWrapper<StudyExamEntity> wrapper = getWrapper(studyExamDto);
        Page<StudyExamEntity> pageEntity = new Page(page.getCurrent(), page.getSize());
        Page<StudyExamEntity> studyExamPage=baseMapper.selectPage(pageEntity,wrapper);
        Page<StudyExamDto> pageDto = new Page(studyExamPage.getCurrent(), studyExamPage.getSize(),studyExamPage.getTotal());
        pageDto.setRecords(ConvertUtil.transformObjList(studyExamPage.getRecords(),StudyExamDto.class));
        return pageDto;
    }

    @Override
    public IPage<StudyExamDto> pageStudyExamExtends(Page<StudyExamDto> page, StudyExamDto studyExamDto){
        Map<String,Long> pageMap = BizCommonUtil.getPageParam(page);
        StudyExamEntity studyExamEntity = ConvertUtil.transformObj(studyExamDto,StudyExamEntity.class);
        List<StudyExamEntity> studyExamList=baseMapper.extendsList(pageMap,studyExamEntity,new HashMap<>());
        Long total = baseMapper.extendsCount(studyExamEntity,new HashMap<>());
        Page<StudyExamDto> pageDto = new Page(page.getCurrent(), page.getSize(),total);
        pageDto.setRecords(ConvertUtil.transformObjList(studyExamList,StudyExamDto.class));
        return pageDto;
    }

    @Override
    public IPage<StudyExamDto> pageStudyExamExtendsApi(Page<StudyExamDto> page, StudyExamDto studyExamDto) {
        Map<String,Long> pageMap = BizCommonUtil.getPageParam(page);
        StudyExamEntity studyExamEntity = ConvertUtil.transformObj(studyExamDto,StudyExamEntity.class);
        Map<String,Object> authorityParams=memberAuthorityService.getAuthorityQueryMap(AuthorityTypeEnum.EXAM.getCode(),WebUtil.currentMember().getId());
        authorityParams.put("isAuthority" , "1");
        List<StudyExamEntity> studyExamList=baseMapper.extendsList(pageMap,studyExamEntity,authorityParams);
        Long total = baseMapper.extendsCount(studyExamEntity,authorityParams);
        Page<StudyExamDto> pageDto = new Page(page.getCurrent(), page.getSize(),total);
        pageDto.setRecords(ConvertUtil.transformObjList(studyExamList,StudyExamDto.class));
        return pageDto;
    }

    @Override
    public StudyExamDto getByIdExtends(Long id){
        StudyExamEntity  studyExamEntity = baseMapper.getByIdExtends(id);
        return ConvertUtil.transformObj(studyExamEntity,StudyExamDto.class);
    }

    @Override
    public List<StudyExamDto> listStudyExam(StudyExamDto studyExamDto){
        QueryWrapper<StudyExamEntity> wrapper = getWrapper(studyExamDto);
        List<StudyExamEntity> list = baseMapper.selectList(wrapper);
        return ConvertUtil.transformObjList(list,StudyExamDto.class);
    }

    @Override
    public void updateStatus(Long id, Integer status) {
        baseMapper.updateStatus(id,status);
    }

    @Override
    public IPage<StudyExamDto> unanswered(Page<StudyExamDto> page, Long memberId) {
        Map<String,Long> pageMap = BizCommonUtil.getPageParam(page);
        Map<String,Object> authorityParams=memberAuthorityService.getAuthorityQueryMap(AuthorityTypeEnum.EXAM.getCode(),memberId);
        List<StudyExamEntity> studyExamList=baseMapper.unansweredList(pageMap,authorityParams);
        Long total = baseMapper.unansweredCount(authorityParams);
        Page<StudyExamDto> pageDto = new Page(page.getCurrent(), page.getSize(),total);
        pageDto.setRecords(ConvertUtil.transformObjList(studyExamList,StudyExamDto.class));
        return pageDto;
    }

    @Override
    public List<StudyExamDto> toRemindList(Long memberId) {
        Map<String,Object> authorityParams=memberAuthorityService.getAuthorityQueryMap(AuthorityTypeEnum.EXAM.getCode(),memberId);
        List<StudyExamDto> studyExamList=ConvertUtil.transformObjList(baseMapper.unansweredList(null,authorityParams),StudyExamDto.class);
        List<StudyExamDto> toRemind= new ArrayList<>();
        for(StudyExamDto dto:studyExamList){
            if(YesNoEnum.YES.getCode().equals(dto.getIsRemind())){
                //开始考试提醒 单位分钟
                if(StrUtil.isNotEmpty(dto.getStartRemind())&&dto.getExamStartTime()!=null){
                    Date startRemindTime = DateUtil.offsetMinute(dto.getExamStartTime(),0-Integer.parseInt(dto.getStartRemind()));
                    if(new Date().compareTo(startRemindTime)>=0){
                        toRemind.add(dto);
                    }
                }else if(StrUtil.isNotEmpty(dto.getEndRemind())&&dto.getExamEndTime()!=null){
                    Date endRemindTime = DateUtil.offsetMinute(dto.getExamEndTime(),0-Integer.parseInt(dto.getStartRemind()));
                    if(new Date().compareTo(endRemindTime)>=0){
                        toRemind.add(dto);
                    }
                }
            }
        }
        return toRemind;
    }

    @Override
    public IPage<StudyExamDto> answeredExams(Page<StudyExamDto> page, Long memberId) {
        Map<String,Long> pageMap = BizCommonUtil.getPageParam(page);
        Map<String,Object> authorityParams=memberAuthorityService.getAuthorityQueryMap(AuthorityTypeEnum.EXAM.getCode(),memberId);
        List<StudyExamEntity> studyExamList=baseMapper.answeredExamsList(pageMap,authorityParams);
        Long total = baseMapper.answeredExamsCount(authorityParams);
        Page<StudyExamDto> pageDto = new Page(page.getCurrent(), page.getSize(),total);
        pageDto.setRecords(ConvertUtil.transformObjList(studyExamList,StudyExamDto.class));
        return pageDto;
    }

    @Override
    public void updateExamStatusJob() {
        QueryWrapper<StudyExamEntity> queryWrapper = new QueryWrapper<>();
        queryWrapper.in("status",ExamStatusEnum.NOT_START.getCode(),ExamStatusEnum.TIME_INTERVAL.getCode(),ExamStatusEnum.GOING.getCode());
        List<StudyExamEntity> list = baseMapper.selectList(queryWrapper);
        List<StudyExamEntity> updateList = new ArrayList<>();
        for(StudyExamEntity entity:list){
            if(ExamStatusEnum.NOT_START.getCode().equals(entity.getStatus())){
                if(entity.getExamStartTime().compareTo(new Date())<=0){
                    entity.setStatus(ExamStatusEnum.GOING.getCode());
                    updateList.add(entity);
                }
            }else if(ExamStatusEnum.TIME_INTERVAL.getCode().equals(entity.getStatus())){
                if(entity.getQuartzTime().compareTo(new Date())>-1){
                    if(entity.getExamStartTime().compareTo(new Date())==-1){
                        entity.setStatus(ExamStatusEnum.NOT_START.getCode());
                    }else{
                        entity.setStatus(ExamStatusEnum.GOING.getCode());
                    }
                    updateList.add(entity);
                }
            }else{
                if(entity.getExamEndTime().compareTo(new Date())<1){
                    entity.setStatus(ExamStatusEnum.FINISH.getCode());
                    updateList.add(entity);
                }
            }
        }
        if(updateList.size()>0){
            this.updateBatchById(updateList);
        }

    }

    @Override
    public IPage<StudyExamDto> endTheExams(Page<StudyExamDto> page, Long memberId) {
        Map<String,Long> pageMap = BizCommonUtil.getPageParam(page);
        Map<String,Object> authorityParams=memberAuthorityService.getAuthorityQueryMap(AuthorityTypeEnum.EXAM.getCode(),memberId);
        List<StudyExamEntity> studyExamList=baseMapper.endTheExamsList(pageMap,authorityParams);
        Long total = baseMapper.endTheExamsCount(authorityParams);
        Page<StudyExamDto> pageDto = new Page(page.getCurrent(), page.getSize(),total);
        pageDto.setRecords(ConvertUtil.transformObjList(studyExamList,StudyExamDto.class));
        return pageDto;
    }

    @Override
    @Async
    public void delExamMemberData(List<Long> ids) {
        if(ids!=null&&ids.size()>0){
            //删除试卷统计信息
            QueryWrapper<StudyExamStatisticsEntity> examStatisticsEntityQueryWrapper = new QueryWrapper<>();
            examStatisticsEntityQueryWrapper.in("exam_id",ids);
            studyExamStatisticsMapper.delete(examStatisticsEntityQueryWrapper);
            //删除会员考试记录
            QueryWrapper<StudyExamStatisticsMemberEntity> examStatisticsMemberEntityQueryWrapper = new QueryWrapper<>();
            examStatisticsMemberEntityQueryWrapper.in("exam_id",ids);
            studyExamStatisticsMemberMapper.delete(examStatisticsMemberEntityQueryWrapper);
            //删除会员试卷
            studyMemberExamMapper.physicalDelete(ids);
            //删除会员未完成试卷信息
            QueryWrapper<StudyMemberUnfinishExamEntity> memberUnfinishExamEntityQueryWrapper = new QueryWrapper<>();
            memberUnfinishExamEntityQueryWrapper.in("exam_id",ids);
            studyMemberUnfinishExamMapper.delete(memberUnfinishExamEntityQueryWrapper);
        }

    }

    @Override
    public StudyExamDto getByIdExamNum(Long id) {
        return baseMapper.getByIdExamNum(id);
    }


}

